home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / apps.to.go / DTS.Lib / AEWFMT.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-07  |  24.0 KB  |  980 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        AEWFMT.c
  5. ** Written by:    Eric Soldan
  6. **
  7. ** Copyright © 1993 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11. /* You may incorporate this sample code into your applications without
  12. ** restriction, though the sample code has been provided "AS IS" and the
  13. ** responsibility for its operation is 100% yours.  However, what you are
  14. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  15. ** after having made changes. If you're going to re-distribute the source,
  16. ** we require that you make it clear in the source that the code was
  17. ** descended from Apple Sample Code, but that you've made changes. */
  18.  
  19.  
  20.  
  21. /*****************************************************************************/
  22.  
  23.  
  24.  
  25. #include "DTS.Lib2.h"
  26. #include "DTS.Lib.protos.h"
  27.  
  28. #ifndef __ERRORS__
  29. #include <Errors.h>
  30. #endif
  31.  
  32. #ifndef __RESOURCES__
  33. #include <Resources.h>
  34. #endif
  35.  
  36. #ifndef __TEXTEDITCONTROL__
  37. #include "TextEditControl.h"
  38. #endif
  39.  
  40. #ifndef __TOOLUTILS__
  41. #include <ToolUtils.h>
  42. #endif
  43.  
  44.  
  45.  
  46. /*****************************************************************************/
  47.  
  48.  
  49.  
  50. extern Boolean            gHasAppleEvents, gQuitApplication;
  51. extern TreeObjHndl        gWindowFormats;
  52.  
  53. static pascal OSErr        ReceiveWFMT(AppleEvent *message, AppleEvent *reply, long refcon);
  54. static void                MergeAppResources(StringPtr suffix);
  55.  
  56. #define keyPascalReply 'PSTR'
  57. #define typePascal     'PSTR'
  58.  
  59.  
  60.  
  61. /*****************************************************************************/
  62.  
  63.  
  64.  
  65. static AEHandler keywordsToInstall[] = {
  66.     { kCustomEventClass, keyWFMTMessage, (AEEventHandlerProcPtr)ReceiveWFMT, nil }
  67. };
  68.  
  69. #define kNumKeywords (sizeof(keywordsToInstall) / sizeof(AEHandler))
  70.  
  71.  
  72.  
  73. /*****************************************************************************/
  74. /*****************************************************************************/
  75.  
  76.  
  77.  
  78. /* Install our custom AppleEvents.  This is done in addition to installing
  79. ** the required AppleEvents.  InitAppleEvents, which installs the required
  80. ** AppleEvents, must be called first, since it sets up some global values. */
  81.  
  82. #pragma segment AppleEvents
  83. void    InitWFMTAppleEvents(void)
  84. {
  85.     OSErr    err;
  86.     short    i;
  87.  
  88.     if (gHasAppleEvents) {
  89.  
  90.         for (i = 0; i < kNumKeywords; ++i) {
  91.  
  92.             if (!keywordsToInstall[i].theUPP)
  93.                 keywordsToInstall[i].theUPP = NewAEEventHandlerProc(keywordsToInstall[i].theHandler);
  94.  
  95.             err = AEInstallEventHandler(
  96.                 keywordsToInstall[i].theEventClass,    /* What class to install.  */
  97.                 keywordsToInstall[i].theEventID,    /* Keywords to install.    */
  98.                 keywordsToInstall[i].theUPP,        /* The AppleEvent handler. */
  99.                 0L,                                    /* Unused refcon.           */
  100.                 false                                /* Only for our app.       */
  101.             );
  102.  
  103.             if (err) {
  104.                 HCenteredAlert(rErrorAlert, nil, gAlertFilterUPP);
  105.                 return;
  106.             }
  107.         }
  108.     }
  109. }
  110.  
  111.  
  112.  
  113. /*****************************************************************************/
  114.  
  115.  
  116.  
  117. /* Send a message to the running application for various application-editing functions.
  118. ** This is used by the AppsToGo application editor for editing running applications. */
  119.  
  120. #pragma segment AppleEvents
  121. OSErr    SendWFMTMessage(FileRecHndl frHndl, TreeObjHndl wobj, short messageType,
  122.                         ResType rtype, short resID, Handle *resHndl, StringPtr suffix)
  123. {
  124.     AEAddressDesc    remoteLoc;
  125.     OSErr            err;
  126.     AppleEvent        theAevt, reply;
  127.     WindowPtr        oldPort;
  128.     Handle            mssgData;
  129.     long            mssgSize, actualSize, oldSize, blockNum;
  130.     DescType        actualType;
  131.     AEKeyword        keym;
  132.     DescType        typem;
  133.     char            hstate;
  134.  
  135.     if (!(*frHndl)->connect.connected) return(noErr);
  136.  
  137.     oldPort = SetFilePort(frHndl);
  138.  
  139.     theAevt.dataHandle = reply.dataHandle = nil;
  140.         /* Make sure disposing of the descriptors is okay in all cases. */
  141.         /* Even though the AppleEvent manager nils out the handle upon failure,
  142.         ** the below code doesn't necessarily call the AppleEvent manager for each
  143.         ** descriptor.  By etting them to nil here, this allows us to just try to
  144.         ** dispose of the descriptors at the bottom of the function. */
  145.  
  146.     remoteLoc = (*frHndl)->connect.remoteLoc;
  147.  
  148.     err = AECreateAppleEvent(        /* CREATE EMPTY APPLEEVENT.     */
  149.         kCustomEventClass,            /* Event class.                 */
  150.         typeWFMTMessage,            /* Event ID.                 */
  151.         &remoteLoc,                    /* Address of receiving app. */
  152.         kAutoGenerateReturnID,        /* This value causes the     */
  153.                                     /* AppleEvent manager to     */
  154.                                     /* assign a return ID that     */
  155.                                     /* is unique to the session. */
  156.         kAnyTransactionID,            /* Ignore transaction ID.     */
  157.         &theAevt                    /* Location of event.         */
  158.     );
  159.  
  160.     if (!err)            /* Say what the message is. */
  161.         AEPutParamPtr(&theAevt, keyDirectObject, typeShortInteger, (Ptr)&messageType, sizeof(short));
  162.  
  163.     if (!err) {
  164.         blockNum = 0;
  165.         AEPutParamPtr(&theAevt, typeBlockNum, typeBlockNum, (Ptr)&blockNum, sizeof(long));
  166.     }
  167.  
  168.     /* The stuff that applies to all messages is now done.  Now specifically
  169.     ** handle all the different message types. */
  170.  
  171.     mssgData = nil;
  172.  
  173.     if (!err) {
  174.  
  175.         if (messageType == kMergeAppResourcesMssg) {
  176.             messageType =  kSetWFMTMssg;
  177.             err = AEPutParamPtr(
  178.                 &theAevt,
  179.                 keyPascalReply,
  180.                 typePascal,
  181.                 (Ptr)suffix,
  182.                 sizeof(Str32)
  183.             );
  184.         }
  185.  
  186.         switch (messageType) {
  187.  
  188.             case kGetWFMTMssg:
  189.                 break;
  190.  
  191.             case kSetWFMTMssg:
  192.                 err = HWriteTree(wobj, mssgData = NewHandle(0));
  193.                 if (!err) {
  194.                     mssgSize = GetHandleSize(mssgData);
  195.                     if (mssgSize > 30000) mssgSize = 30000;
  196.                     HLock(mssgData);
  197.                     err = AEPutParamPtr(
  198.                         &theAevt,
  199.                         keyWFMTMessage,
  200.                         typeWFMTMessage,
  201.                         *mssgData,
  202.                         mssgSize
  203.                     );
  204.                     HUnlock(mssgData);
  205.                 }
  206.                 break;
  207.  
  208.             case kGetAppResourceMssg:
  209.                 err = AEPutParamPtr(
  210.                     &theAevt,
  211.                     typeRSRCType,
  212.                     typeRSRCType,
  213.                     (Ptr)&rtype,
  214.                     sizeof(ResType)
  215.                 );
  216.                 if (!err) {
  217.                     err = AEPutParamPtr(
  218.                         &theAevt,
  219.                         typeRSRCID,
  220.                         typeRSRCID,
  221.                         (Ptr)&resID,
  222.                         sizeof(short)
  223.                     );
  224.                 }
  225.                 break;
  226.  
  227.             case kSetAppResourceMssg:
  228.                 err = AEPutParamPtr(
  229.                     &theAevt,
  230.                     typeRSRCType,
  231.                     typeRSRCType,
  232.                     (Ptr)&rtype,
  233.                     sizeof(ResType)
  234.                 );
  235.                 if (!err) {
  236.                     err = AEPutParamPtr(
  237.                         &theAevt,
  238.                         typeRSRCID,
  239.                         typeRSRCID,
  240.                         (Ptr)&resID,
  241.                         sizeof(short)
  242.                     );
  243.                 }
  244.                 if (!err) {
  245.                     hstate = HGetState(*resHndl);
  246.                     HLock(*resHndl);
  247.                     mssgSize = GetHandleSize(*resHndl);
  248.                     err = AEPutParamPtr(
  249.                         &theAevt,
  250.                         keyWFMTMessage,
  251.                         typeWFMTMessage,
  252.                         **resHndl,
  253.                         mssgSize
  254.                     );
  255.                     HSetState(*resHndl, hstate);
  256.                 }
  257.                 if (!err) {
  258.                     err = AESend(                    /* SEND APPLEEVENT.                */
  259.                         &theAevt,                    /* Our Apple Event to send.        */
  260.                         &reply,                        /* We may have a reply.            */
  261.                         kAEWaitReply,
  262.                         kAENormalPriority,            /* App. send priority.            */
  263.                         300,
  264.                         nil,                        /* No wait, no filter.            */
  265.                         nil                            /* EventFilterProcPtr.            */
  266.                     );
  267.                 }
  268.                 break;
  269.         }
  270.     }
  271.  
  272.     if (!err) {
  273.         if ((messageType == kGetWFMTMssg) || (messageType == kGetAppResourceMssg)) {
  274.  
  275.             if (resHndl) *resHndl = nil;
  276.  
  277.             mssgData = NewHandle(0);
  278.             for (;;) {
  279.  
  280.                 err = AESend(                    /* SEND APPLEEVENT.                */
  281.                     &theAevt,                    /* Our Apple Event to send.        */
  282.                     &reply,                        /* We may have a reply.            */
  283.                     kAEWaitReply,
  284.                     kAENormalPriority,            /* App. send priority.            */
  285.                     300,
  286.                     nil,                        /* No wait, no filter.            */
  287.                     nil                            /* EventFilterProcPtr.            */
  288.                 );
  289.                 if (err) break;
  290.  
  291.                 keym  = (messageType == kGetWFMTMssg) ? keyWFMTMessage  : keyRSRCMessage;
  292.                 typem = (messageType == kGetWFMTMssg) ? typeWFMTMessage : typeRSRCMessage;
  293.                 err = AEGetParamPtr(
  294.                     &reply,                    /* The AppleEvent.              */
  295.                     keym,                    /* AEKeyword                 */
  296.                     typem,                    /* Desired type.             */
  297.                     &actualType,            /* Type code.                 */
  298.                     nil,                    /* Pointer to area for data. */ 
  299.                     0,                        /* Size of data area.         */
  300.                     &mssgSize                /* Returned size of data.     */
  301.                 );
  302.                 if (err) break;
  303.  
  304.                 oldSize = GetHandleSize(mssgData);
  305.                 SetHandleSize(mssgData, oldSize + mssgSize);
  306.                 err = MemError();
  307.                 if (err) break;
  308.  
  309.                 HLock(mssgData);
  310.                 err = AEGetParamPtr(
  311.                     &reply,                    /* The AppleEvent.              */
  312.                     keym,                    /* AEKeyword                 */
  313.                     typem,                    /* Desired type.             */
  314.                     &actualType,            /* Type code.                 */
  315.                     *mssgData + oldSize,    /* Pointer to area for data. */ 
  316.                     mssgSize,                /* Size of data area.         */
  317.                     &actualSize                /* Returned size of data.     */
  318.                 );
  319.                 HUnlock(mssgData);
  320.                 if (err) break;
  321.  
  322.                 if (mssgSize < 30000) break;
  323.  
  324.                 ++blockNum;
  325.                 err = AEPutParamPtr(
  326.                     &theAevt,
  327.                     typeBlockNum,
  328.                     typeBlockNum,
  329.                     (Ptr)&blockNum,
  330.                     sizeof(long)
  331.                 );
  332.                 if (err) break;
  333.  
  334.             }
  335.  
  336.             if (messageType == kGetWFMTMssg) {
  337.                 if (!err)
  338.                     HReadTree(wobj, mssgData);
  339.                 if (mssgData)
  340.                     DisposeHandle(mssgData);
  341.             }
  342.             else {
  343.                 if (err) {
  344.                     if (mssgData) {
  345.                         DisposeHandle(mssgData);
  346.                         mssgData = nil;
  347.                     }
  348.                 }
  349.                 *resHndl = mssgData;
  350.             }
  351.         }
  352.     }
  353.  
  354.     if (!err) {        /* If everything looks good... */
  355.         if (messageType == kSetWFMTMssg) {
  356.             do {
  357.                 if (err) {
  358.                     if (mssgData) {
  359.                         DisposeHandle(mssgData);
  360.                         mssgData = nil;
  361.                     }
  362.                     break;
  363.                 }
  364.                 err = AESend(                    /* SEND APPLEEVENT.                */
  365.                     &theAevt,                    /* Our Apple Event to send.        */
  366.                     &reply,                        /* We may have a reply.            */
  367.                     kAEWaitReply,
  368.                     kAENormalPriority,            /* App. send priority.            */
  369.                     300,
  370.                     nil,                        /* No wait, no filter.            */
  371.                     nil                            /* EventFilterProcPtr.            */
  372.                 );
  373.                 if (err) continue;
  374.                 if (mssgData) {
  375.                     mssgSize = GetHandleSize(mssgData);
  376.                     if (mssgSize < 30000) {
  377.                         DisposeHandle(mssgData);
  378.                         mssgData = nil;
  379.                         break;
  380.                     }
  381.                     mssgSize -= 30000;
  382.                     BlockMove(*mssgData + 30000, *mssgData, mssgSize);
  383.                     SetHandleSize(mssgData, mssgSize);
  384.                     if (mssgSize > 30000) mssgSize = 30000;
  385.                     HLock(mssgData);
  386.                     err = AEPutParamPtr(
  387.                         &theAevt,
  388.                         keyWFMTMessage,
  389.                         typeWFMTMessage,
  390.                         *mssgData,
  391.                         mssgSize
  392.                     );
  393.                     HUnlock(mssgData);
  394.                     if (err) continue;
  395.                     ++blockNum;
  396.                     err = AEPutParamPtr(
  397.                         &theAevt,
  398.                         typeBlockNum,
  399.                         typeBlockNum,
  400.                         (Ptr)&blockNum,
  401.                         sizeof(long)
  402.                     );
  403.                 }
  404.             } while (mssgData);
  405. #if 0
  406.             if (!err) {
  407.                 AEDisposeDesc(&theAevt);
  408.                 AEDisposeDesc(&reply);
  409.                 err = AECreateAppleEvent(        /* CREATE EMPTY APPLEEVENT.     */
  410.                     kCoreEventClass,            /* Event class.                 */
  411.                     kAEOpenApplication,            /* Event ID.                 */
  412.                     &remoteLoc,                    /* Address of receiving app. */
  413.                     kAutoGenerateReturnID,        /* This value causes the     */
  414.                                                 /* AppleEvent manager to     */
  415.                                                 /* assign a return ID that     */
  416.                                                 /* is unique to the session. */
  417.                     kAnyTransactionID,            /* Ignore transaction ID.     */
  418.                     &theAevt                    /* Location of event.         */
  419.                 );
  420.                 if (!err) {
  421.                     err = AESend(                    /* SEND APPLEEVENT.                */
  422.                         &theAevt,                    /* Our Apple Event to send.        */
  423.                         &reply,                        /* We may have a reply.            */
  424.                         kAEWaitReply,
  425.                         kAENormalPriority,            /* App. send priority.            */
  426.                         300,
  427.                         nil,                        /* No wait, no filter.            */
  428.                         nil                            /* EventFilterProcPtr.            */
  429.                     );
  430.                 }
  431.             }
  432. #endif
  433.         }
  434.     }
  435.  
  436.     AEDisposeDesc(&theAevt);
  437.     AEDisposeDesc(&reply);
  438.         /* Dispose of the descriptors, created or not.  If not created, no harm done by calling. */
  439.  
  440.     SetPort(oldPort);
  441.     return(err);
  442. }
  443.  
  444.  
  445.  
  446. /*****************************************************************************/
  447.  
  448.  
  449.  
  450. #pragma segment AppleEvents
  451. static pascal OSErr    ReceiveWFMT(AppleEvent *message, AppleEvent *reply, long refcon)
  452. {
  453. #ifndef __MWERKS__
  454. #pragma unused (reply, refcon)
  455. #endif
  456.  
  457.     OSErr            err;
  458.     short            messageType, oldRes, i, vRefNum, resID;
  459.     char            hstate;
  460.     ResType            rtype;
  461.     Handle            oldr, rsrc;
  462.     WindowPtr        window;
  463.     FileRecHndl        frHndl;
  464.     DescType        actualType;
  465.     long            actualSize, dirID, blockNum, blockBeg, blockSiz;
  466.     MenuHandle        menu;
  467.     long            mssgSize, ms;
  468.     Str32            fileName, suffix;
  469.     Handle            mssgData;
  470.     static Handle    accumMssgData;
  471.     static short    count;
  472.  
  473.     err = AEGetParamPtr(        /* GET THE MESSAGE TYPE.     */
  474.         message,                /* The AppleEvent.              */
  475.         keyDirectObject,        /* AEKeyword                 */
  476.         typeShortInteger,        /* Desired type.             */
  477.         &actualType,            /* Type code.                 */
  478.         (Ptr)&messageType,        /* Pointer to area for data. */ 
  479.         sizeof(short),            /* Size of data area.         */
  480.         &actualSize                /* Returned size of data.     */
  481.     );
  482.  
  483.     if (!err) {        /* If everything is cool, then do the specific task... */
  484.  
  485.         switch(messageType) {
  486.  
  487.             case kGetWFMTMssg:
  488.                 mssgData = GetAppResource('WFMT', 128, &err);
  489.                 if ((!mssgData) && (!err)) err = resNotFound;
  490.                 if (mssgData) {
  491.                     DetachResource(mssgData);
  492.                     err = AEGetParamPtr(
  493.                         message,
  494.                         typeBlockNum,
  495.                         typeBlockNum,
  496.                         &actualType,
  497.                         (Ptr)&blockNum,
  498.                         sizeof(long),
  499.                         &actualSize
  500.                     );
  501.                     if (!err) {
  502.                         mssgSize = GetHandleSize(mssgData);
  503.                         blockBeg = blockNum * 30000;
  504.                         blockSiz = mssgSize - blockBeg;
  505.                         if (blockSiz < 0)     blockSiz = 0;
  506.                         if (blockSiz > 30000) blockSiz = 30000;
  507.                         HLock(mssgData);
  508.                         err = AEPutParamPtr(
  509.                             reply,
  510.                             keyWFMTMessage,
  511.                             typeWFMTMessage,
  512.                             *mssgData + blockBeg,
  513.                             blockSiz
  514.                         );
  515.                     }
  516.                     DisposeHandle(mssgData);
  517.                     mssgData = nil;
  518.                 }
  519.                 break;
  520.  
  521.             case kSetWFMTMssg:
  522.             case kMergeAppResourcesMssg:
  523.                 err = AEGetParamPtr(
  524.                     message,
  525.                     typeBlockNum,
  526.                     typeBlockNum,
  527.                     &actualType,
  528.                     (Ptr)&blockNum,
  529.                     sizeof(long),
  530.                     &actualSize
  531.                 );
  532.                 if (err) break;
  533.                 err = AEGetParamPtr(
  534.                     message,                /* The AppleEvent.              */
  535.                     keyWFMTMessage,            /* AEKeyword                 */
  536.                     typeWFMTMessage,        /* Desired type.             */
  537.                     &actualType,            /* Type code.                 */
  538.                     nil,                    /* Pointer to area for data. */ 
  539.                     0,                        /* Size of data area.         */
  540.                     &mssgSize                /* Returned size of data.     */
  541.                 );
  542.                 if (err) break;
  543.  
  544.                 if ((blockNum) && (!accumMssgData)) {
  545.                     err = memFullErr;
  546.                     break;
  547.                 }
  548.  
  549.                 if (!blockNum)
  550.                     if (!accumMssgData)
  551.                         accumMssgData = NewHandle(0);
  552.  
  553.                 SetHandleSize(accumMssgData, blockNum * 30000 + mssgSize);
  554.                 err = MemError();
  555.                 if (err) {
  556.                     DisposeHandle(accumMssgData);
  557.                     accumMssgData = nil;
  558.                     break;
  559.                 }
  560.  
  561.                 HLock(accumMssgData);
  562.                 err = AEGetParamPtr(
  563.                     message,                            /* The AppleEvent.              */
  564.                     keyWFMTMessage,                        /* AEKeyword                 */
  565.                     typeWFMTMessage,                    /* Desired type.             */
  566.                     &actualType,                        /* Type code.                 */
  567.                     *accumMssgData + blockNum * 30000,    /* Pointer to area for data. */ 
  568.                     mssgSize,                            /* Size of data area.         */
  569.                     &actualSize                            /* Returned size of data.     */
  570.                 );
  571.                 HUnlock(accumMssgData);
  572.  
  573.                 if (mssgSize == 30000) break;        /* More blocks to come. */
  574.  
  575.                 if (!err) {
  576.                     while ((window = GetNextWindow(nil, 0)) != nil) {
  577.                         frHndl = (FileRecHndl)GetWRefCon(window);
  578.                         (*frHndl)->fileState.docDirty = false;
  579.                             /* Prevent save-before-closing dialogs. */
  580.                         (*frHndl)->fileState.attributes &= (0xFFFFFFFFL - kwHideOnClose);
  581.                             /* Make sure that we aren't just hiding old windows. */
  582.                         DisposeOneWindow(window, kClose);
  583.                         gQuitApplication = false;
  584.                             /* App may only have one window, and when it is closed,
  585.                             ** the app quits.  This behavior of the app is like DA's.
  586.                             ** Prevent the app from quitting. */
  587.                     }
  588.                     if (!err) {
  589.                         oldRes = CurResFile();
  590.                         UseResFile(gAppResRef);
  591.                         SetResLoad(false);
  592.                         oldr = Get1Resource('WFMT', 128);
  593.                         SetResLoad(true);
  594.                         if (oldr) {
  595.                             ms = GetHandleSize(accumMssgData);
  596.                             ReallocateHandle(oldr, ms);
  597.                             err = MemError();
  598.                             if (!err) {
  599.                                 BlockMove(*accumMssgData, *oldr, ms);
  600.                                 ChangedResource(oldr);
  601.                                 WriteResource(oldr);
  602.                                 UpdateResFile(gAppResRef);
  603.                                 DetachResource(oldr);
  604.                                 DisposeHandle(oldr);
  605.                             }
  606.                         }
  607.                         else {
  608.                             AddResource(accumMssgData, 'WFMT', 128, nil);
  609.                             ChangedResource(accumMssgData);
  610.                             WriteResource(accumMssgData);
  611.                             UpdateResFile(gAppResRef);
  612.                             DetachResource(accumMssgData);
  613.                         }
  614.                         if (!GetFileLocation(gAppResRef, &vRefNum, &dirID, fileName))
  615.                             FlushVol(nil, vRefNum);
  616.                         UseResFile(oldRes);
  617.                     }
  618.                     HReadWindowFormats(accumMssgData);
  619.                 }
  620.  
  621.                 if (accumMssgData) {
  622.                     DisposeHandle(accumMssgData);
  623.                     accumMssgData = nil;
  624.                 }
  625.  
  626.                 if (messageType == kMergeAppResourcesMssg) {
  627.                     oldRes = CurResFile();
  628.                     UseResFile(gAppResRef);
  629.                     for (i = Count1Resources('MENU'); i; --i) {
  630.                         menu = (MenuHandle)Get1IndResource('MENU', i);
  631.                         if (!menu) continue;
  632.                         if (GetMenuHandle(**(short **)menu) == menu) DeleteMenu(**(short **)menu);
  633.                         ReleaseResource((Handle)menu);
  634.                     }
  635.                     UseResFile(oldRes);
  636.                 }
  637.  
  638.                 if (messageType == kMergeAppResourcesMssg) {
  639.                     pcpy(suffix, "\p copy");
  640.                     AEGetParamPtr(
  641.                         message,
  642.                         keyPascalReply,
  643.                         typePascal,
  644.                         &actualType,
  645.                         (Ptr)suffix,
  646.                         sizeof(Str32),
  647.                         &actualSize
  648.                     );
  649.                     MergeAppResources(suffix);
  650.                 }
  651.  
  652.                 if (messageType == kMergeAppResourcesMssg) {
  653.                     UseResFile(gAppResRef);
  654.                     StandardMenuSetup(rMenuBar, mApple);
  655.                     UseResFile(oldRes);
  656.                 }
  657.  
  658.                 OpenRuntimeOnlyAutoNewWindows();
  659.                 DoOpenApplication();
  660.                 DoAEOpenApplication(nil, nil, 0L);
  661.  
  662.                 break;
  663.  
  664.             case kGetAppResourceMssg:
  665.                 err = AEGetParamPtr(
  666.                     message,
  667.                     typeRSRCType,
  668.                     typeRSRCType,
  669.                     &actualType,
  670.                     (Ptr)&rtype,
  671.                     sizeof(ResType),
  672.                     &actualSize
  673.                 );
  674.                 if (!err) {
  675.                     err = AEGetParamPtr(
  676.                         message,
  677.                         typeRSRCID,
  678.                         typeRSRCID,
  679.                         &actualType,
  680.                         (Ptr)&resID,
  681.                         sizeof(long),
  682.                         &actualSize
  683.                     );
  684.                 }
  685.                 if (!err) {
  686.                     rsrc = GetAppResource(rtype, resID, nil);
  687.                     if (rsrc) {
  688.                         hstate = HGetState(rsrc);
  689.                         HLock(rsrc);
  690.                         err = AEGetParamPtr(
  691.                             message,
  692.                             typeBlockNum,
  693.                             typeBlockNum,
  694.                             &actualType,
  695.                             (Ptr)&blockNum,
  696.                             sizeof(long),
  697.                             &actualSize
  698.                         );
  699.                         if (!err) {
  700.                             mssgSize = GetHandleSize(rsrc);
  701.                             blockBeg = blockNum * 30000;
  702.                             blockSiz = mssgSize - blockBeg;
  703.                             if (blockSiz < 0)     blockSiz = 0;
  704.                             if (blockSiz > 30000) blockSiz = 30000;
  705.                             err = AEPutParamPtr(
  706.                                 reply,
  707.                                 keyRSRCMessage,
  708.                                 typeRSRCMessage,
  709.                                 *rsrc + blockBeg,
  710.                                 mssgSize
  711.                             );
  712.                         }
  713.                         HSetState(rsrc, hstate);
  714.                     }
  715.                 }
  716.                 break;
  717.  
  718.             case kSetAppResourceMssg:
  719.                 err = AEGetParamPtr(
  720.                     message,
  721.                     typeRSRCType,
  722.                     typeRSRCType,
  723.                     &actualType,
  724.                     (Ptr)&rtype,
  725.                     sizeof(ResType),
  726.                     &actualSize
  727.                 );
  728.                 if (!err) {
  729.                     err = AEGetParamPtr(
  730.                         message,
  731.                         typeRSRCID,
  732.                         typeRSRCID,
  733.                         &actualType,
  734.                         (Ptr)&resID,
  735.                         sizeof(long),
  736.                         &actualSize
  737.                     );
  738.                 }
  739.                 err = AEGetParamPtr(
  740.                     message,                /* The AppleEvent.              */
  741.                     keyWFMTMessage,            /* AEKeyword                 */
  742.                     typeWFMTMessage,        /* Desired type.             */
  743.                     &actualType,            /* Type code.                 */
  744.                     nil,                    /* Pointer to area for data. */ 
  745.                     0,                        /* Size of data area.         */
  746.                     &mssgSize                /* Returned size of data.     */
  747.                 );
  748.                 if (err) break;
  749.                 mssgData = NewHandle(mssgSize);
  750.                 if (!mssgData) break;
  751.                 HLock(mssgData);
  752.                 err = AEGetParamPtr(
  753.                     message,                /* The AppleEvent.              */
  754.                     keyWFMTMessage,            /* AEKeyword                 */
  755.                     typeWFMTMessage,        /* Desired type.             */
  756.                     &actualType,            /* Type code.                 */
  757.                     *mssgData,                /* Pointer to area for data. */ 
  758.                     mssgSize,                /* Size of data area.         */
  759.                     &actualSize                /* Returned size of data.     */
  760.                 );
  761.                 HUnlock(mssgData);
  762.                 if (!err) {
  763.                     oldRes = CurResFile();
  764.                     UseResFile(gAppResRef);
  765.                     oldr = Get1Resource(rtype, resID);
  766.                     if (oldr) {
  767.                         RemoveResource(oldr);
  768.                         DisposeHandle(oldr);
  769.                     }
  770.                     AddResource(mssgData, rtype, resID, nil);
  771.                     ChangedResource(mssgData);
  772.                     WriteResource(mssgData);
  773.                     UpdateResFile(gAppResRef);
  774.                     DetachResource(mssgData);
  775.                     if (!GetFileLocation(gAppResRef, &vRefNum, &dirID, fileName))
  776.                         FlushVol(nil, vRefNum);
  777.                     UseResFile(oldRes);
  778.                 }
  779.                 DisposeHandle(mssgData);
  780.                 break;
  781.         }
  782.     }
  783.  
  784.     return(err);
  785. }
  786.  
  787.  
  788.  
  789.  
  790. /*****************************************************************************/
  791. /*****************************************************************************/
  792. /*****************************************************************************/
  793.  
  794.  
  795.  
  796. #pragma segment AppleEvents
  797. static void    MergeAppResources(StringPtr suffix)
  798. {
  799.     short                oldRes, numAppTypes, numAppItems, numCpyTypes, numCpyItems;
  800.     short                tt, ii, dd, mergeRsrc, rid, cid, vRefNum;
  801.     char                appAttr, cpyAttr;
  802.     ResType                appType, cpyType, rtype, ddType, ctype;
  803.     long                l, cpySize, dirID;
  804.     ProcessSerialNumber    psn;
  805.     ProcessInfoRec        pinfo;
  806.     FSSpec                fss;
  807.     Str255                rname, cname;
  808.     Str32                dontDo, fileName;
  809.     Handle                appr, cpyr;
  810.     OSErr                err;
  811.  
  812.     oldRes = CurResFile();
  813.  
  814.     pinfo.processInfoLength = sizeof(ProcessInfoRec);
  815.     pinfo.processName       = gAppName;
  816.     pinfo.processAppSpec    = &fss;
  817.  
  818.     psn.lowLongOfPSN  = kCurrentProcess;
  819.     psn.highLongOfPSN = kNoProcess;
  820.     GetProcessInformation(&psn, &pinfo);
  821.  
  822.     pcat(fss.name, suffix);
  823.  
  824.     SetResLoad(false);
  825.     mergeRsrc = HOpenResFile(fss.vRefNum, fss.parID, fss.name, fsRdPerm);
  826.     err = ResError();
  827.     SetResLoad(true);
  828.     if (err) return;
  829.  
  830.     UseResFile(gAppResRef);
  831.     numAppTypes = Count1Types();
  832.  
  833.     for (tt = numAppTypes; tt; --tt) {
  834.         Get1IndType(&appType, tt);
  835.         numAppItems = Count1Resources(appType);
  836.  
  837.         for (ii = numAppItems; ii; --ii) {
  838.  
  839.             appr = Get1IndResource(appType, ii);
  840.             if (!appr) continue;
  841.  
  842.             GetResInfo(appr, &rid, &rtype, rname);
  843.             appAttr  = GetResAttrs(appr);
  844.  
  845.             if (rtype == 'WFMT') continue;
  846.                 /* ResEdit doesn't modify this one.  DTSFW.App.Editor does. */
  847.  
  848.             if ((rtype == 'STR#') && (rid == 128)) continue;
  849.                 /* This is the resource that describes what resources can be replaced/modified.
  850.                 ** We don't want to replace or modify what is telling us what to do. */
  851.  
  852.             for (dd = 1;; ++dd) {
  853.                 GetIndString(dontDo, 128, dd);
  854.                 if (!dontDo[0]) break;
  855.                 BlockMove(dontDo + 1, &ddType, sizeof(long));
  856.                 if (appType == ddType) break;
  857.             }
  858.             if (dontDo[0]) continue;
  859.  
  860.             UseResFile(mergeRsrc);
  861.             cpyr = Get1Resource(rtype, rid);
  862.             if (cpyr) {
  863.                 GetResInfo(cpyr, &cid, &ctype, cname);
  864.                 cpyAttr = GetResAttrs(cpyr);
  865.                 DetachResource(cpyr);
  866.                 HNoPurge(cpyr);
  867.             }
  868.             UseResFile(gAppResRef);
  869.             appr = Get1IndResource(appType, ii);        /* In case it's purgeable and got purged. */
  870.             if (!appr) {                                /* Just to be really safe. */
  871.                 DisposeHandle(cpyr);
  872.                 continue;
  873.             }
  874.  
  875.             if (!cpyr) {
  876.                 RemoveResource(appr);
  877.                 DisposeHandle(appr);
  878.                 continue;
  879.             }
  880.  
  881.             if (appAttr != cpyAttr) {
  882.                 SetResAttrs(appr, cpyAttr);
  883.                 ChangedResource(appr);
  884.                 WriteResource(appr);
  885.             }
  886.             appr = Get1IndResource(appType, ii);        /* In case it's purgeable and got purged. */
  887.             if (!appr) {                                /* Just to be really safe. */
  888.                 DisposeHandle(cpyr);
  889.                 continue;
  890.             }
  891.  
  892.             if (pcmp(rname, cname)) {
  893.                 SetResInfo(appr, rid, cname);
  894.                 ChangedResource(appr);
  895.                 WriteResource(appr);
  896.             }
  897.             appr = Get1IndResource(appType, ii);        /* In case it's purgeable and got purged. */
  898.             if (!appr) {                                /* Just to be really safe. */
  899.                 DisposeHandle(cpyr);
  900.                 continue;
  901.             }
  902.  
  903.             if (GetHandleSize(appr) != (cpySize = GetHandleSize(cpyr))) {
  904.                 HNoPurge(appr);
  905.                 HUnlock(appr);
  906.                 SetHandleSize(appr, cpySize);
  907.                 err = MemError();
  908.                 SetResAttrs(appr, cpyAttr);
  909.                 if (err) {
  910.                     DisposeHandle(cpyr);
  911.                     continue;
  912.                 }
  913.                 BlockMove(*cpyr, *appr, cpySize);
  914.                 ChangedResource(appr);
  915.                 WriteResource(appr);
  916.                 DisposeHandle(cpyr);
  917.                 continue;
  918.             }
  919.  
  920.             for (l = 0; l < cpySize; ++l) {
  921.                 if ((*appr)[l] != (*cpyr)[l]) {
  922.                     BlockMove(*cpyr, *appr, cpySize);
  923.                     ChangedResource(appr);
  924.                     WriteResource(appr);
  925.                     DisposeHandle(cpyr);
  926.                     break;
  927.                 }
  928.             }
  929.             if (l < cpySize) continue;
  930.  
  931.             DisposeHandle(cpyr);
  932.         }
  933.     }
  934.  
  935.     UseResFile(mergeRsrc);
  936.     numCpyTypes = Count1Types();
  937.  
  938.     for (tt = numCpyTypes; tt; --tt) {
  939.         Get1IndType(&cpyType, tt);
  940.         numCpyItems = Count1Resources(cpyType);
  941.  
  942.         for (ii = numCpyItems; ii; --ii) {
  943.  
  944.             cpyr = Get1IndResource(cpyType, ii);
  945.             if (!cpyr) continue;
  946.  
  947.             cpyAttr = GetResAttrs(cpyr);
  948.             GetResInfo(cpyr, &cid, &ctype, cname);
  949.             DetachResource(cpyr);
  950.  
  951.             UseResFile(gAppResRef);
  952.             appr = Get1Resource(ctype, cid);
  953.             UseResFile(mergeRsrc);
  954.  
  955.             if (!appr) {
  956.                 UseResFile(gAppResRef);
  957.                 AddResource(cpyr, ctype, cid, cname);
  958.                 SetResAttrs(cpyr, cpyAttr);
  959.                 ChangedResource(cpyr);
  960.                 WriteResource(cpyr);
  961.                 DetachResource(cpyr);
  962.                 UseResFile(mergeRsrc);
  963.             }
  964.  
  965.             DisposeHandle(cpyr);
  966.         }
  967.     }
  968.  
  969.     CloseResFile(mergeRsrc);
  970.     UpdateResFile(gAppResRef);
  971.  
  972.     if (!GetFileLocation(gAppResRef, &vRefNum, &dirID, fileName))
  973.         FlushVol(nil, vRefNum);
  974.  
  975.     UseResFile(oldRes);
  976. }
  977.  
  978.  
  979.  
  980.